#include "napi/native_api.h"
#include "bx/thread.h"
#include <cstdint>
#include <cstdio>
#include <unistd.h>

const char *GENERICALLOC_TAG = "ohtest";

static napi_value Add(napi_env env, napi_callback_info info)
{
	size_t argc = 2;
	napi_value args[2] = {nullptr};

	napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

	napi_valuetype valuetype0;
	napi_typeof(env, args[0], &valuetype0);

	napi_valuetype valuetype1;
	napi_typeof(env, args[1], &valuetype1);

	double value0;
	napi_get_value_double(env, args[0], &value0);

	double value1;
	napi_get_value_double(env, args[1], &value1);

	napi_value sum;
	napi_create_double(env, value0 + value1, &sum);

	return sum;
}

napi_value callPicker(napi_env env, napi_callback_info info)
{
	napi_value result = nullptr;

	napi_value thisVar = nullptr;
	size_t argCount = 3;
	napi_value argValue[3] = {0};

	if (napi_get_cb_info(env, info, &argCount, argValue, &thisVar, nullptr) != napi_ok || argCount < 1 || argValue[0] == nullptr)
	{
		//return nullptr;
	}
	napi_status status;
	napi_value mod;
	status = napi_load_module(env, "@ohos.hilog", &mod);
	if (status != napi_ok)
		return result;

	status = napi_load_module(env, "@kit.ArkUI", &mod);
	if (status != napi_ok)
		return result;

	//status = napi_load_module(env, "PandoraPicker", &mod);
	//status = napi_load_module(env, "ets/defaultability/util", &mod);
	status = napi_load_module_with_info(env, "pandorapicker", "com.pixui.myapplication/entry_test", &mod);
	if (status != napi_ok)
		return result;

	napi_value clazz;
	status = napi_get_named_property(env, mod, "PandoraPicker", &clazz);
	if (status != napi_ok)
		return result;

	napi_value func;
	status = napi_get_named_property(env, clazz, "openGallery", &func);
	if (status != napi_ok)
		return result;

	napi_valuetype vt;
	napi_typeof(env, func, &vt);
	napi_get_boolean(env, vt == napi_function, &result);
	return result;
}

napi_value callTestLib(napi_env env, napi_callback_info info)
{
	napi_value result = nullptr;

	napi_value thisVar = nullptr;
	size_t argCount = 3;
	napi_value argValue[3] = {0};

	if (napi_get_cb_info(env, info, &argCount, argValue, &thisVar, nullptr) != napi_ok || argCount < 1 || argValue[0] == nullptr)
	{
		//return nullptr;
	}
	napi_status status;
	napi_value mod;

	//已验证：系统模块可以加载
	status = napi_load_module(env, "@ohos.hilog", &mod);
	if (status != napi_ok)
		return result;

	//已知：@kit下的模块不能动态加载
	status = napi_load_module(env, "@kit.ArkUI", &mod);
	if (status != napi_ok)
	{
		//已验证：主动获取清除异常，可以保证不crash
		napi_value err;
		napi_get_and_clear_last_exception(env, &err);
	}

	//已验证，本模块内ets文件可加载
	status = napi_load_module(env, "ets/entryability/EntryAbility", &mod);
	if (status != napi_ok)
		return result;

	//已验证：ohosTest下的ets文件加载方式与外部har类似
	status = napi_load_module_with_info(env, "entry/src/ohosTest/ets/test/Ability.test", "com.pixui.myapplication/entry_test", &mod);
	if (status != napi_ok)
		return result;

	//已验证：外部har中的模块可以加载
	status = napi_load_module_with_info(env, "testlib", "com.pixui.myapplication/entry_test", &mod);
	if (status != napi_ok)
		return result;

	napi_value clazz;
	status = napi_get_named_property(env, mod, "TestHello", &clazz);
	if (status != napi_ok)
		return result;

	napi_value func;
	status = napi_get_named_property(env, clazz, "say", &func);
	if (status != napi_ok)
		return result;

	napi_valuetype vt;
	napi_typeof(env, func, &vt);
	napi_get_boolean(env, vt == napi_function, &result);
	return result;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
	napi_property_descriptor desc[] = {
			{"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr},
			{"callPicker", nullptr, callPicker, nullptr, nullptr, nullptr, napi_default, nullptr},
			{"callTestLib", nullptr, callTestLib, nullptr, nullptr, nullptr, napi_default, nullptr},
	};
	napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
	return exports;
}
EXTERN_C_END

static napi_module demoModule = {
		.nm_version = 1,
		.nm_flags = 0,
		.nm_filename = nullptr,
		.nm_register_func = Init,
		.nm_modname = "entry",
		.nm_priv = ((void *) 0),
		.reserved = {0},
};

#include <hilog/log.h>

bx::Thread thread[40];
int32_t gThreadFn(bx::Thread *self, void *_userData)
{
	while (true)
	{
		void *handle = self->getThreadHandle();
		OH_LOG_Print(LOG_APP, LOG_INFO, 0xff00, "ohtest", "run in thread:%{public}d, tid:%{public}p\n", (int) (intptr_t) _userData, handle);
		if (handle)
			break;
		else
			::sleep(0);
	}
	self->setThreadName();


	return 0;
}
extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
	napi_module_register(&demoModule);
	for (int i = 0; i < sizeof(thread) / sizeof(thread[0]); i++)
	{
		char name[128];
		sprintf(name, "testoh_thread_%d", i);
		thread[i].init(gThreadFn, (void *) (intptr_t) i, 0, name);
	}
}
